package com.ldk.api.handler;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.config.AlipayConfig;
import com.ldk.api.Consts;
import com.ldk.base.framework.util.BeanUtil;
import com.ldk.base.framework.util.SystemUtil;
import com.ldk.framework.entity.Alipay;
import com.ldk.framework.entity.ServiceTrip;
import com.ldk.framework.entity.Tenpay;
import com.ldk.framework.enums.OutTradeNoSuffix;
import com.ldk.framework.enums.PayType;
import com.ldk.framework.enums.ServiceCode;
import com.ldk.framework.service.ITenpayService;
import com.ldk.framework.unionpay.PayUtils;
import com.weixin.api.WxMpService;
import com.weixin.api.WxMpServiceImpl;
import com.weixin.bean.result.WxMpPrepayIdResult;
import com.weixin.common.util.crypto.WxCryptUtil;
import com.weixin.util.WxConfig;

/**
 * 行程业务基类
 *
 * @author xiangwl
 *         2017年3月23日
 *         com.ldk.api.handler
 *         BZBaseRequestHandler
 */
public abstract class BZBaseRequestHandler extends BaseRequestHandler {

    @Autowired
    protected ITenpayService tenpayService;

    /**
     * 设置行程支付定金回调参数
     *
     * @param trip
     * @param payId 支付宝 微信
     * @param ip    微信支付时 客户端终端IP,其他支付时为空
     * @return
     * @throws Exception
     */
    protected Map<String, Object> setTripPayDepositCallback(ServiceTrip trip, int payId, String ip) throws Exception {
        if (trip == null) {
            throw new Exception("行程不存在");
        }
        if (payId != PayType.Alipay.getId() && payId != PayType.Tenpay.getId()) {
            throw new Exception("支付方式不对");
        }
        Double depositFee = trip.getDepositPayFee() == null ? 0 : trip.getDepositPayFee();
        if (depositFee <= 0) {
            throw new Exception("支付定金金额小于等于0");
        }
        Map<String, Object> result = BeanUtil.toMapByFastjson(trip);
        String tripNo = trip.getTripNo();
        String outTradeNo = tripNo + OutTradeNoSuffix.Deposit.getSuffix();
        String serviceCodeName = ServiceCode.getCodeName(trip.getServiceCode());
        String body = Consts.SystemName + serviceCodeName + "行程定金支付";
        if (payId == PayType.Alipay.getId()) {
            result.put("callbackUrl", Consts.DEPOSIT_PAYNOTIFY_ALIPAY_CALLBACK_URL);
            result.put("outTradeNo", outTradeNo);
            AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", AlipayConfig.app_id, AlipayConfig.private_key, "json", AlipayConfig.input_charset, AlipayConfig.ali_public_key, AlipayConfig.sign_type);
            AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
            AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
            model.setBody(body);
            model.setSubject("会达出行");
            model.setOutTradeNo(outTradeNo);
            model.setSellerId(AlipayConfig.partner);
            model.setTimeoutExpress("90m");
            model.setTotalAmount(depositFee + "");
            model.setProductCode("QUICK_MSECURITY_PAY");

            request.setBizModel(model);
            request.setNotifyUrl(Consts.DEPOSIT_PAYNOTIFY_ALIPAY_CALLBACK_URL);

            String aliPrePayResult = "";
            try {
                AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
                aliPrePayResult = response.getBody();
                logger.error("aliPrePayResult=" + aliPrePayResult);
            } catch (Exception e) {
                logger.error(e.getMessage());
            }
            result.put("aliPrePayResult", aliPrePayResult);
        } else if (payId == PayType.Tenpay.getId()) {
            float amt = depositFee.floatValue();
            String tradeType = "APP";
            WxMpService wxMpService = new WxMpServiceImpl();
            WxMpPrepayIdResult prepayIdResult = wxMpService.getPrepayId("", outTradeNo, amt, body, tradeType, ip, Consts.DEPOSIT_PAYNOTIFY_TENPAY_CALLBACK_URL);
            logger.error("setTripPayDepositCallback.prepayIdResult=" + JSON.toJSONString(prepayIdResult));
            //如果获取成功
            if (prepayIdResult.isResultSuccess()) {
                //设置回调地址
                result.put("callbackUrl", Consts.DEPOSIT_PAYNOTIFY_TENPAY_CALLBACK_URL);
                result.put("outTradeNo", outTradeNo);

                String nonce_str = SystemUtil.getAllSeconds() + "";
                String timestamp = SystemUtil.getAllSeconds() + "";

                SortedMap<String, String> packageParams = new TreeMap<String, String>();
                packageParams.put("appid", WxConfig.AppId);
                packageParams.put("noncestr", nonce_str);
                packageParams.put("package", "Sign=WXPay");
                packageParams.put("partnerid", prepayIdResult.getMch_id());
                packageParams.put("prepayid", prepayIdResult.getPrepay_id());
                packageParams.put("timestamp", timestamp);

                String sign = WxCryptUtil.createSign(packageParams, WxConfig.SignKey);

                Map<String, Object> wxResultMap = new HashMap<String, Object>();
                wxResultMap.put("appid", WxConfig.AppId);
                wxResultMap.put("partnerid", prepayIdResult.getMch_id());
                wxResultMap.put("prepayid", prepayIdResult.getPrepay_id());
                wxResultMap.put("noncestr", nonce_str);
                wxResultMap.put("timestamp", timestamp);
                wxResultMap.put("packages", "Sign=WXPay");//android package是关键字，不能解析，换作packages
                wxResultMap.put("sign", sign);

                result.put("wxPrePayResult", wxResultMap);

                try {
                    //同时新增微信支付记录
                    Tenpay tenpay = new Tenpay();
                    tenpay.setAppid(prepayIdResult.getAppid());
                    tenpay.setBody(body);
                    tenpay.setMchId(prepayIdResult.getMch_id());
                    tenpay.setOutTradeNo(outTradeNo);
                    ;
                    tenpay.setTradeType(tradeType);
                    tenpay.setTotalFee(depositFee);
                    tenpay.setTimeStart(SystemUtil.getDateString(new Date(), "yyyyMMddHHmmss"));
                    tenpay.setSpbillCreateIp(ip);
                    tenpay.setPrepayId(prepayIdResult.getPrepay_id());
                    tenpay.setCodeUrl(prepayIdResult.getCode_url());
                    tenpay.setOpenid("");

                    tenpayService.insert("", tenpay);
                } catch (Exception e) {
                    logger.error(e.getMessage());
                }
            }
        }
        return result;
    }

    /**
     * 设置行程支付行程剩余费用回调参数
     *
     * @param trip
     * @param payId 支付宝 微信
     * @param ip    微信支付时 客户端终端IP,其他支付时为空
     * @return
     * @throws Exception
     */
    protected Map<String, Object> setTripPayFeeCallback(ServiceTrip trip, int payId, String ip) throws Exception {
        if (trip == null) {
            throw new Exception("行程不存在");
        }
        if (payId != PayType.Alipay.getId() && payId != PayType.Tenpay.getId() && payId != PayType.UnionPay.getId()) {
            throw new Exception("支付方式不对");
        }
        Double payFee = trip.getPayFee() == null ? 0 : trip.getPayFee();
        //2018-12-14 mqy 将第三方支付设为1分钱
       //payFee=0.01;
        if (payFee <= 0) {
            throw new Exception("行程费用金额小于等于0");
        }
        Map<String, Object> result = BeanUtil.toMapByFastjson(trip);
        String tripNo = trip.getTripNo();
        String outTradeNo = tripNo + OutTradeNoSuffix.Balance.getSuffix();
        String serviceCodeName = ServiceCode.getCodeName(trip.getServiceCode());
        String body = Consts.SystemName + serviceCodeName + "行程支付";
        if (payId == PayType.Alipay.getId()) {
            result.put("callbackUrl", Consts.PAYNOTIFY_ALIPAY_CALLBACK_URL);
            result.put("outTradeNo", outTradeNo);
            AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", AlipayConfig.app_id, AlipayConfig.private_key, "json", AlipayConfig.input_charset, AlipayConfig.ali_public_key, AlipayConfig.sign_type);
            AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
            AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
            model.setBody(body);
            model.setSubject(Consts.SystemName);
            model.setOutTradeNo(outTradeNo);
            model.setSellerId(AlipayConfig.partner);
            model.setTimeoutExpress("90m");
            model.setTotalAmount(payFee + "");
            model.setProductCode("QUICK_MSECURITY_PAY");

            request.setBizModel(model);
            request.setNotifyUrl(Consts.PAYNOTIFY_ALIPAY_CALLBACK_URL);

            String aliPrePayResult = "";
            try {
                AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
                aliPrePayResult = response.getBody();
                logger.error("aliPrePayResult=" + aliPrePayResult);
            } catch (Exception e) {
                logger.error(e.getMessage());
            }
            result.put("aliPrePayResult", aliPrePayResult);
        } else if (payId == PayType.Tenpay.getId()) {
            float amt = payFee.floatValue();
            String tradeType = "APP";
            WxMpService wxMpService = new WxMpServiceImpl();
            WxMpPrepayIdResult prepayIdResult = wxMpService.getPrepayId("", outTradeNo, amt, body, tradeType, ip, Consts.PAYNOTIFY_TENPAY_CALLBACK_URL);
            logger.error("setTripPayFeeCallback.prepayIdResult=" + JSON.toJSONString(prepayIdResult));
            //如果获取成功
            if (prepayIdResult.isResultSuccess()) {
                //设置回调地址
                result.put("callbackUrl", Consts.PAYNOTIFY_TENPAY_CALLBACK_URL);
                result.put("outTradeNo", outTradeNo);

                String nonce_str = SystemUtil.getAllSeconds() + "";
                String timestamp = SystemUtil.getAllSeconds() + "";

                SortedMap<String, String> packageParams = new TreeMap<String, String>();
                packageParams.put("appid", WxConfig.AppId);
                packageParams.put("noncestr", nonce_str);
                packageParams.put("package", "Sign=WXPay");
                packageParams.put("partnerid", prepayIdResult.getMch_id());
                packageParams.put("prepayid", prepayIdResult.getPrepay_id());
                packageParams.put("timestamp", timestamp);

                String sign = WxCryptUtil.createSign(packageParams, WxConfig.SignKey);

                Map<String, Object> wxResultMap = new HashMap<String, Object>();
                wxResultMap.put("appid", WxConfig.AppId);
                wxResultMap.put("partnerid", prepayIdResult.getMch_id());
                wxResultMap.put("prepayid", prepayIdResult.getPrepay_id());
                wxResultMap.put("noncestr", nonce_str);
                wxResultMap.put("timestamp", timestamp);
                wxResultMap.put("packages", "Sign=WXPay");//android package是关键字，不能解析，换作packages
                wxResultMap.put("sign", sign);

                result.put("wxPrePayResult", wxResultMap);

                try {
                    //同时新增微信支付记录
                    Tenpay tenpay = new Tenpay();
                    tenpay.setAppid(prepayIdResult.getAppid());
                    tenpay.setBody(body);
                    tenpay.setMchId(prepayIdResult.getMch_id());
                    tenpay.setOutTradeNo(outTradeNo);
                    tenpay.setTradeType(tradeType);
                    tenpay.setTotalFee(payFee);
                    tenpay.setTimeStart(SystemUtil.getDateString(new Date(), "yyyyMMddHHmmss"));
                    tenpay.setSpbillCreateIp(ip);
                    tenpay.setPrepayId(prepayIdResult.getPrepay_id());
                    tenpay.setCodeUrl(prepayIdResult.getCode_url());
                    tenpay.setOpenid("");

                    tenpayService.insert("", tenpay);
                } catch (Exception e) {
                    logger.error(e.getMessage());
                }
            }
        } else if (payId == PayType.UnionPay.getId()) {
            // Map<String, Object> result = BeanUtil.toMapByFastjson(trip);
            String tn = PayUtils.UnionPay(tripNo, (int) (payFee * 100));
            result.put("tn", tn);
        }
        return result;
    }
}
